package edu.stanford.prpl.facade.templates;

import java.io.*;
import java.util.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.net.URLEncoder;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import edu.stanford.prpl.facade.UIEngine;
import edu.stanford.prpl.facade.UIEngine.devicePlatform;
import edu.stanford.prpl.facade.android.*;

/* Android specific */
import android.app.*;
import android.net.Uri;
import android.util.Log;
import android.view.*;
import android.view.View.OnClickListener;
import android.widget.*;
import android.widget.AdapterView.OnItemClickListener;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import edu.stanford.prpl.android.*; // TO-DO: Figure out a way to remove this!



public class NaviListPageUITemplate extends UITemplate
{
    public static final String iui_html_template = "NaviListPageUI.html";
	
	private String listPageTitleFormat = null;
	private Map<String,DynNaviListUITemplate> sublistTemplates
	= new HashMap<String,DynNaviListUITemplate>();

	
	public NaviListPageUITemplate(devicePlatform dP)
	{
		super("dynUI:listPage", dP);
		sublistTemplates.put("*", new DynNaviListUITemplate("*", this.selectedPlatform));
	}


	public void parseTemplate(XmlPullParser xpp) throws Exception
	{
	    // Assumes to be at the starting tag for the current UI template
		// <dynUI:listPage dataObjectName="...">
		xpp.require(XmlPullParser.START_TAG, null, "dynUI:listPage");
		
		int numAttributes = xpp.getAttributeCount();
		for (int i = 0; i < numAttributes; i++)
		{
			if (xpp.getAttributeName(i).equals("dataObjectName"))
			   this.dataObjectName = xpp.getAttributeValue(i);
		}

	    super.parseTemplate(xpp); // Common XML processing code

	    // Assert Invariant (b)
	    xpp.require(XmlPullParser.END_TAG, null, "dynUI:listPage");
	}

    protected void processTemplateStartElement (XmlPullParser xpp) throws Exception
    {
        String name = xpp.getName();
        String uri = xpp.getNamespace();

        //if ("".equals (uri)) {
        //    System.out.println("Start element: " + name);
        //} else {
        //    System.out.println("Start element: {" + uri + "}" + name);
        //}        

        if (name.equals("dynUI:listPageTitleFormat"))
        {
           String format = xpp.nextText();
           if (format.length() > 0)
              this.listPageTitleFormat = format;         
        }
        else if (name.equals("dynUI:list"))
        {
           DynNaviListUITemplate listObj = new DynNaviListUITemplate(this.selectedPlatform);
           listObj.parseTemplate(xpp);
           if (listObj.dataObjectName == null)
           {
              DynNaviListUITemplate genListObj = sublistTemplates.get("*");
              genListObj.listEntryTemplates.putAll(listObj.listEntryTemplates);
           }
           else
               sublistTemplates.put(listObj.dataObjectName, listObj);
        }
    }



    public void parseData(XmlPullParser xpp, UIModelData currentUIData) throws Exception
    {   
        // Assumes to be at the starting tag 
        // xpp.require(XmlPullParser.START_TAG, null, this.dataObjectName);
        
        super.parseData(xpp, currentUIData); // Common XML processing code
        
        // xpp.require(XmlPullParser.END_TAG, null, this.dataObjectName);
    }    

    protected void processDataStartElement (XmlPullParser xpp, UIModelData currentUIData) throws Exception
    {
        String name = xpp.getName();
        String uri = xpp.getNamespace();

        //if ("".equals (uri)) {
        //    System.out.println("Start element: " + name);
        //} else {
        //    System.out.println("Start element: {" + uri + "}" + name);
        //}

        // Check if current data element is mapped to a List UI widget
        DynNaviListUITemplate sublistUITemplate = sublistTemplates.get(name);
        if (sublistUITemplate == null)
            sublistUITemplate = sublistTemplates.get("*");
       
        // PROBLEM: How to solve for non-existent sublist tags?
        UIModelData sublistUIData = new UIModelData();
        sublistUIData.uiTemplate = sublistUITemplate;
        sublistUITemplate.parseData(xpp, sublistUIData);
        
        // ArrayList<Map> sublistsUI
        // System.out.println("Adding another sublist...");
        currentUIData.childUIElementsData.add(sublistUIData);
    }
    
    // For Main Page generation
    public void generateUI(UIModelData currentUIData, Object platformData)
    {
        // Generate HTML string
        if (this.selectedPlatform == UIEngine.devicePlatform.WEB)
        {
            generateWebUI(currentUIData, platformData);
        }
        else if (this.selectedPlatform == UIEngine.devicePlatform.ANDROID)
        {
        	generateAndroidUI(currentUIData, platformData);
        }
        else
        {
        	currentUIData.uiObject = null;
        }
    }    


    private void generateWebUI(UIModelData currentUIData, Object platformData)
    {
        String UI_htmlcode = "";
        String PageTitle;

        PageTitle = currentUIData.attributesStore.get("_PageTitle"); // Rendering-specified title
        if (PageTitle == null)
        {
            // Template-specified title
            PageTitle = UIModelData.fillStrWithAttr(currentUIData, this.listPageTitleFormat).trim();
        }

        UI_htmlcode += "\t<ul id=\"home\" title=\""+PageTitle+"\" selected=\"true\">";

        // Now for the sublists
        Iterator<UIModelData> childUI_iterator = currentUIData.childUIElementsData.iterator();  
        while (childUI_iterator.hasNext())
        {
            UIModelData childUI_data = childUI_iterator.next();
            childUI_data.uiTemplate.generateUI(childUI_data, platformData);
            if (childUI_data.uiObject != null)
                UI_htmlcode += ((String)childUI_data.uiObject);
        }

        UI_htmlcode += "\n\t</ul>";
        // String filename = "DynNaviListPageUI.html";
        String mainpage_htmlcode;

        try 
        {
        	// Get HTML template code from HTML file residing with java class
            InputStream is = getClass().getResourceAsStream(NaviListPageUITemplate.iui_html_template);
            if (is == null)
               throw new IOException("HTML code for NaviListPageUI mainpage not found!!!");
            
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            StringBuffer sb = new StringBuffer();
            String line;
            while ((line = br.readLine()) != null) 
            {
              sb.append(line);
            }
            br.close();
            isr.close();
            is.close();
            
            mainpage_htmlcode = sb.toString();
        }
        catch (IOException ioe)
        {   
            mainpage_htmlcode = UI_htmlcode;
            System.out.println("IOException: "+ioe);    
        }
        
        
        // Detect the phrase [[DYNUICODE]] and replace it
        String UI_styling =
	    "<style type=\"text/css\" media=\"screen\">@import \"iui/iui.css\";</style>  \n" +
	    "<script type=\"application/x-javascript\" src=\"iui/iui.js\"></script>      \n" +
	    "<style type=\"text/css\" media=\"screen\">@import \"facade.css\";</style>   \n" + // Comment out to get square-ish styling
	    "<script type=\"application/x-javascript\" src=\"facade.js\"></script>       \n";  // Comment out to get square-ish styling
        
        mainpage_htmlcode = mainpage_htmlcode.replaceFirst("\\[\\[PAGETITLE\\]\\]", PageTitle);
        mainpage_htmlcode = mainpage_htmlcode.replaceFirst("\\[\\[PAGE_UI_STYLING\\]\\]", UI_styling);
        mainpage_htmlcode = mainpage_htmlcode.replaceFirst("\\[\\[DYNUICODE\\]\\]", UI_htmlcode);

        currentUIData.uiObject = mainpage_htmlcode;
    }

    private void generateAndroidUI(UIModelData currentUIData, Object platformData)
    {   
    	View dynNaviListPageUI;
    	Activity appActivity;
    	LayoutInflater mInflater;
        String PageTitle;

        if (!(platformData instanceof Activity))
           return;
        appActivity = (Activity)platformData;

        PageTitle = currentUIData.attributesStore.get("_PageTitle"); // Rendering-specified title
        if (PageTitle == null)
        {
            // Template-specified title
            PageTitle = UIModelData.fillStrWithAttr(currentUIData, this.listPageTitleFormat).trim();
        }
        
        
        // Build Android native UI
        mInflater = LayoutInflater.from(appActivity);
        dynNaviListPageUI = (View)mInflater.inflate(R.layout.prpl_facade_navi_list,
        									        null, false);
        ListView dynNaviListUI = (ListView)dynNaviListPageUI.findViewById(R.id.naviList);
        ArrayList<View> dynNaviListItemsUI = new ArrayList<View>();

        // Now for the sublists
        Iterator<UIModelData> childUI_iterator = currentUIData.childUIElementsData.iterator();
        while (childUI_iterator.hasNext())
        {
            UIModelData childUI_data = childUI_iterator.next();
            childUI_data.uiTemplate.generateUI(childUI_data, platformData);
            if (childUI_data.uiObject != null)
            {
            	ArrayList<View> dynNaviSublistUI = (ArrayList<View>)childUI_data.uiObject;
            	dynNaviListItemsUI.addAll(dynNaviSublistUI);
            }
        }

        DynNaviListAdapter mAdapter
        = new DynNaviListAdapter(appActivity, R.layout.prpl_facade_navi_list_item, dynNaviListItemsUI);
        dynNaviListUI.setAdapter(mAdapter);

        // Setup call back to Application/Actvity code to handle certain types of
        // user-interaction with UI, such as the clicking of a selection
        DynNaviListActionResponder responder = DynNaviListActionResponder.getInstance();
        if (platformData instanceof FacadeAndroidData)
        {
        	FacadeAndroidData appData = (FacadeAndroidData)platformData;
        	responder.appListItemClickResponse = appData.getAppListItemClickResponse();
        }

        dynNaviListUI.setOnItemClickListener(responder.mListItemClickEvent);
        
        // Returns an Android UI object (a View obj)
        currentUIData.uiObject = dynNaviListPageUI;
    }


    // For UI fragment to be passed through AJAX
    public void generateUIFragment(UIModelData currentUIData, Object platformData)
    {
        // Generate HTML string
        if (this.selectedPlatform == UIEngine.devicePlatform.WEB)
        {
            String UI_htmlcode = "";
            // String pageTitle = UIModelData.fillStrWithAttr(currentUIData, this.listPageTitleFormat).trim();
            String pageTitle = currentUIData.attributesStore.get("_PageTitle");
            String pageTitleURLEncoded;

            // System.out.println("Start: "+(new Date().getTime()/1000));
            
            if (pageTitle == null) pageTitle = "";
            try {
                pageTitleURLEncoded = URLEncoder.encode(pageTitle, "UTF-8");
            } 
            catch(UnsupportedEncodingException e) { 
                pageTitleURLEncoded = "";
            }

            UI_htmlcode += "\t<ul id=\""+pageTitleURLEncoded+"\" title=\""+pageTitle+"\">";

            // Now for the sublists
            Iterator<UIModelData> childUI_iterator = currentUIData.childUIElementsData.iterator();
            while (childUI_iterator.hasNext())
            {
                UIModelData childUI_data = childUI_iterator.next();
                childUI_data.uiTemplate.generateUI(childUI_data, platformData);
                if (childUI_data.uiObject != null)
                    UI_htmlcode += ((String)childUI_data.uiObject);
            }

            UI_htmlcode += "\n\t</ul>";          
            currentUIData.uiObject = UI_htmlcode;
            // System.out.println("End: "+(new Date().getTime()/1000));
        }
        // else if (this.selectedPlatform == UIEngine.devicePlatform.ANDROID)
        // {
        //    
        // }   
    }
    
    
    private static String readFileAsString(String filePath) throws java.io.IOException
    {
        StringBuilder fileData = new StringBuilder(1000);
        BufferedReader reader = new BufferedReader(new FileReader(filePath));
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1)
        {
            fileData.append(buf, 0, numRead);
        }
        reader.close();
        return fileData.toString();
    }    





	/* Internal Classes */

	private class DynNaviListUITemplate extends UITemplate
	{
		private String listTitleFormat = null;
		private Map<String,DynNaviListEntryUITemplate> listEntryTemplates
		= new HashMap<String,DynNaviListEntryUITemplate>();
		
		DynNaviListUITemplate(devicePlatform dP)
		{   super("dynUI:list", dP);   }

        DynNaviListUITemplate(String objNameMapping, devicePlatform dP)
        {     
            super("dynUI:list", dP);
            this.dataObjectName = objNameMapping;
        }		
		
		public void parseTemplate(XmlPullParser xpp) throws Exception
		{
	        // Expects to be at the starting tag 
	        // <dynUI:list ...>	        
	        xpp.require(XmlPullParser.START_TAG, null, "dynUI:list");

	        int numAttributes = xpp.getAttributeCount();
	        for (int i = 0; i < numAttributes; i++)
	        {
	            if (xpp.getAttributeName(i).equals("dataObjectName"))
	               this.dataObjectName = xpp.getAttributeValue(i);
	        }

	        super.parseTemplate(xpp);
	        xpp.require(XmlPullParser.END_TAG, null, "dynUI:list");   
		}
		
        protected void processTemplateStartElement (XmlPullParser xpp) throws Exception
        {
            String name = xpp.getName();
            String uri = xpp.getNamespace();

            //if ("".equals (uri)) {
            //    System.out.println("Start element: " + name);
            //} else {
            //    System.out.println("Start element: {" + uri + "}" + name);
            //}        

            if (name.equals("dynUI:listTitleFormat"))
            {
               String format = xpp.nextText();
               if (format.length() > 0)
                  this.listTitleFormat = format;
            }
            else if (name.equals("dynUI:listEntry"))
            {
               DynNaviListEntryUITemplate listEntryObj = new DynNaviListEntryUITemplate(this.selectedPlatform);
               listEntryObj.parseTemplate(xpp);
               if (listEntryObj.dataObjectName != null)
               {
                  listEntryTemplates.put(listEntryObj.dataObjectName, listEntryObj);
               }
            }
        }



        public void parseData(XmlPullParser xpp, UIModelData currentUIData) throws Exception
        {   
            // Assumes to be at the starting tag 
            // xpp.require(XmlPullParser.START_TAG, null, this.dataObjectName);           
                        
            super.parseData(xpp, currentUIData); // Common XML processing code

            // xpp.require(XmlPullParser.END_TAG, null, this.dataObjectName);
        }    

        protected void processDataStartElement (XmlPullParser xpp, UIModelData currentUIData) throws Exception
        {
            String name = xpp.getName();
            String uri = xpp.getNamespace();

            //if ("".equals (uri)) {
            //    System.out.println("Start element: " + name);
            //} else {
            //    System.out.println("Start element: {" + uri + "}" + name);
            //}

            // Check if current data element is mapped to a ListEntry UI widget
            DynNaviListEntryUITemplate listEntryUITemplate = listEntryTemplates.get(name);
            if (listEntryUITemplate == null)
            {
                // Process as additional attributes for current List UI widget
                if (!this.dataObjectName.equals("*"))
                {
                    String value;
                    try {
                        value = xpp.nextText();
                    } catch(XmlPullParserException e) {
                        return;
                    }
                    currentUIData.attributesStore.put(name, value);
                }
            }
            else
            {
                UIModelData listEntryUIData = new UIModelData();
                listEntryUIData.uiTemplate = listEntryUITemplate;
                listEntryUITemplate.parseData(xpp, listEntryUIData);
                
                // ArrayList<Map> listEntriesUI
                currentUIData.childUIElementsData.add(listEntryUIData);
            }
        }

        public void generateUI(UIModelData currentUIData, Object platformData)
        {            
            // Generate HTML string
            if (this.selectedPlatform == UIEngine.devicePlatform.WEB)
            {
            	generateWebUI(currentUIData, platformData);
            }
            else if (this.selectedPlatform == UIEngine.devicePlatform.ANDROID)
            {
            	generateAndroidUI(currentUIData, platformData);
            }
            else
            {
            	currentUIData.uiObject = null;
            }
        }

    	private void generateWebUI(UIModelData currentUIData, Object platformData)
    	{
            Boolean showSublistHeader = true;
            
            // Should not show a sublist header UI widget
            if (this.dataObjectName == null || this.listTitleFormat == null)
                showSublistHeader = false;
            
            String UI_htmlcode = "";
            
            if (showSublistHeader) 
            {
                UI_htmlcode += "\n\t\t<li class=\"group\">";
                UI_htmlcode += UIModelData.fillStrWithAttr(currentUIData, this.listTitleFormat).trim();
                UI_htmlcode += "</li>";
            }

            // Now for the entries in the sublist
            Iterator<UIModelData> childUI_iterator = currentUIData.childUIElementsData.iterator();
            
            while (childUI_iterator.hasNext())
            {
                UIModelData childUI_data = childUI_iterator.next();
                childUI_data.uiTemplate.generateUI(childUI_data, platformData);
                if (childUI_data.uiObject != null)
                    UI_htmlcode += "\n\t\t"+((String)childUI_data.uiObject);
            }
            
            currentUIData.uiObject = UI_htmlcode;
    	}
        
    	private void generateAndroidUI(UIModelData currentUIData, Object platformData)        
    	{
    		ArrayList<View> dynNaviSublistUI = new ArrayList<View>();
    		Boolean showSublistHeader = true;
            
            // Should not show a sublist header UI widget
            if (this.dataObjectName == null || this.listTitleFormat == null)
                showSublistHeader = false;
            
            String UI_htmlcode = "";
            
            if (showSublistHeader) 
            {
                // Gives you the sublist title
            	// UIModelData.fillStrWithAttr(currentUIData, this.listTitleFormat).trim();
                
            	// Emulate a sublist title in Android UI
            	// - Could create a list entry with a distinct UI style from other normal list entries
            	// - Make it non-clickable
            }
    		
            // Now for the entries in the sublist
            Iterator<UIModelData> childUI_iterator = currentUIData.childUIElementsData.iterator();
            
            while (childUI_iterator.hasNext())
            {
                UIModelData childUI_data = childUI_iterator.next();
                childUI_data.uiTemplate.generateUI(childUI_data, platformData);
                if (childUI_data.uiObject != null)
                {
                	View dynNaviListItemUI = (View)childUI_data.uiObject;
                	dynNaviSublistUI.add(dynNaviListItemUI);
                }
            }
            
            
            // Returns an ArrayList of views, each of which is a View object representing 
    		// a list entry (clickable) or a sublist title (non-clickable)
    		currentUIData.uiObject = dynNaviSublistUI;
    	}
    		
	}
	
	


	private enum listEntryActions 
	{ NONE, SHOW_NEWLISTPAGE, EXPAND_SUBLIST, SHOW_CUSTOMPAGE, EXTERNAL_LINK }
	private enum listEntryActionCallTypes 
	{ NONE, WEB, ANDROID_INTENTION, IPHONE_PROCESS }
	
	private class DynNaviListEntryUITemplate extends UITemplate
	{
	    private String listEntryFormat = null;
	    private String listEntryImage = null;
	    private listEntryActions listEntryAction = listEntryActions.NONE;
	    private String listEntryActionCall = null;
	    private String listEntryNewPageTitle = null;
	    private listEntryActionCallTypes listEntryActionCallType = listEntryActionCallTypes.NONE;

		DynNaviListEntryUITemplate(devicePlatform dP)
		{
		    super("dynUI:listEntry", dP);
		}
		
		public void parseTemplate(XmlPullParser xpp) throws Exception
		{
            // Expects to be at the starting tag 
            // <dynUI:listEntry ...>         
            xpp.require(XmlPullParser.START_TAG, null, "dynUI:listEntry");

            int numAttributes = xpp.getAttributeCount();
            for (int i = 0; i < numAttributes; i++)
            {
                if (xpp.getAttributeName(i).equals("dataObjectName"))
                   this.dataObjectName = xpp.getAttributeValue(i);
            }

            super.parseTemplate(xpp);
            xpp.require(XmlPullParser.END_TAG, null, "dynUI:listEntry");
            
		}
		
	    protected void processTemplateStartElement (XmlPullParser xpp) throws Exception
	    {
            String name = xpp.getName();
            String uri = xpp.getNamespace();

            //if ("".equals (uri)) {
            //    System.out.println("Start element: " + name);
            //} else {
            //    System.out.println("Start element: {" + uri + "}" + name);
            //}        

            if (name.equals("dynUI:listEntryFormat"))
            {
               String format = xpp.nextText();
               if (format.length() > 0)
                  this.listEntryFormat = format;
            }
            else if (name.equals("dynUI:listEntryImage"))
            {
               String format = xpp.nextText();
               if (format.length() > 0)
                  this.listEntryImage = format;
            }
            else if (name.equals("dynUI:listEntryAction"))
            {
               String action = xpp.nextText();
               if (action.equals("showNewListPage"))
                  this.listEntryAction = listEntryActions.SHOW_NEWLISTPAGE;
               else if (action.equals("expandSublist"))
                  this.listEntryAction = listEntryActions.EXPAND_SUBLIST;
               else if (action.equals("showCustomPage"))
                  this.listEntryAction = listEntryActions.SHOW_CUSTOMPAGE;
               else if (action.equals("externalLink"))
                  this.listEntryAction = listEntryActions.EXTERNAL_LINK;
            }
            else if (name.equals("dynUI:listEntryNewPageTitle"))
            {
               String newpageTitle = xpp.nextText();
               if (newpageTitle.length() > 0)
                  this.listEntryNewPageTitle = newpageTitle;
            }            
            else if (name.equals("dynUI:listEntryActionCall"))
            {
               String actionCall = xpp.nextText();
               if (actionCall.length() > 0)
                  this.listEntryActionCall = actionCall;
               
               int numAttributes = xpp.getAttributeCount();
               for (int i = 0; i < numAttributes; i++)
               {
                   if (xpp.getAttributeName(i).equals("callType"))
                   {
                      String callType = xpp.getAttributeValue(i);
                      
                      if (callType.equals("web"))
                         this.listEntryActionCallType = listEntryActionCallTypes.WEB;
                       else if (callType.equals("androidIntention"))
                         this.listEntryActionCallType = listEntryActionCallTypes.ANDROID_INTENTION;
                       else if (callType.equals("iPhoneProcess"))
                         this.listEntryActionCallType = listEntryActionCallTypes.IPHONE_PROCESS;
                   }
               }
            }
	    
	    }



        // UI
        // attributesStore: a HashMap of attribute values - Containing text-only        
        public void parseData(XmlPullParser xpp, UIModelData currentUIData) throws Exception
        {   
            // Assumes to be at the starting tag 
            // xpp.require(XmlPullParser.START_TAG, null, this.dataObjectName);

            // Attributes from <xmltag attr="..."
            
            super.parseData(xpp, currentUIData); // Common XML processing code

            // xpp.require(XmlPullParser.END_TAG, null, this.dataObjectName);
        }

        protected void processDataStartElement (XmlPullParser xpp, UIModelData currentUIData) throws Exception
        {
            String name = xpp.getName();
            String uri = xpp.getNamespace();

            //if ("".equals (uri)) {
            //    System.out.println("Start element: " + name);
            //} else {
            //    System.out.println("Start element: {" + uri + "}" + name);
            //}

            // Treat xml elements value as attributes data 
            try 
            {
            	String value = null;
                value = xpp.nextText();
                if (value != null && value.trim().length() > 0)
                   currentUIData.attributesStore.put(name, value);
            } 
            catch(XmlPullParserException e) 
            {
                return;
            }

        }	
        
        public void generateUI(UIModelData currentUIData, Object platformData)
        {
            // Hide this UI list entry widget
            if (this.listEntryFormat == null)
                return;
            
            // Generate HTML string
            if (this.selectedPlatform == UIEngine.devicePlatform.WEB)
            {
            	generateWebUI(currentUIData, platformData);
            }
            else if (this.selectedPlatform == UIEngine.devicePlatform.ANDROID)
            {
            	generateAndroidUI(currentUIData, platformData);
            }
            else
            {
            	currentUIData.uiObject = null;
            }
        }
        
        private void generateWebUI(UIModelData currentUIData, Object platformData)
        {
            String UI_htmlcode = "<li>";
            String listEntryText 
            = UIModelData.fillStrWithAttr(currentUIData, this.listEntryFormat).trim();

            
            if (this.listEntryAction == listEntryActions.SHOW_NEWLISTPAGE)
            {                   
                String pageTitle = "", actionCall = "";
                     
                try {
                    if (this.listEntryNewPageTitle != null) {
                        pageTitle = UIModelData.fillStrWithAttr(currentUIData, this.listEntryNewPageTitle).trim();
                        pageTitle = URLEncoder.encode(pageTitle, "UTF-8");
                    }
                    if (this.listEntryActionCall != null){
                        actionCall = UIModelData.fillStrWithAttr(currentUIData, this.listEntryActionCall).trim();
                        actionCall = URLEncoder.encode(actionCall, "UTF-8");
                    }
                } 
                catch(UnsupportedEncodingException e)
                { }

                // Whether a thumbnail should be displayed for this list-entry
                if (this.listEntryImage != null)
                {
                    String picAddr = UIModelData.fillStrWithAttr(currentUIData, this.listEntryImage).trim();
                    // If XML does not specify a thumbnail, don't show anything
                    if (!picAddr.equals(this.listEntryImage))
                    	listEntryText = "<img style=\"border: medium none; vertical-align: middle; \" height=60px width=60px src=\""+picAddr+"\"/>"
                                        + "<span style=\"padding-left: 25px;\">"+listEntryText+"</span>";
                    else
                    	listEntryText 
                        = "<div style=\"padding-left: 10px; padding-top: 12px;\">"+listEntryText+"</div>";
                }
                else
                	listEntryText 
                    = "<div style=\"padding-left: 10px; padding-top: 12px;\">"+listEntryText+"</div>";
                

                if (this.listEntryActionCall != null)
                {
                    UI_htmlcode += "<a href=\"processor.jsp?pageTitle="+pageTitle+"&actionCall="+actionCall+"\">"+listEntryText+"</a></li>";
                }
                else
                    UI_htmlcode += listEntryText+"</li>";
            }
            else if (this.listEntryAction == listEntryActions.EXTERNAL_LINK)
            {
                UI_htmlcode += "<a href=\""+this.listEntryActionCall+"\" target=\"_self\">"+listEntryText+"</a></li>";
            }
            // else if (this.listEntryAction == listEntryActions.SHOW_CUSTOMPAGE)
            // {
            //     
            // }
            
            currentUIData.uiObject = UI_htmlcode;
        }
        
        private void generateAndroidUI(UIModelData currentUIData, Object platformData)
        {
            View dynNaviListItemUI = null;
        	Activity appActivity;
            LayoutInflater mInflater;
            
            String listEntryText = UIModelData.fillStrWithAttr(currentUIData, this.listEntryFormat).trim();
            if (listEntryText == null || listEntryText.length() <= 0)
                return;
            
            if (!(platformData instanceof Activity))
                return;
            appActivity = (Activity)platformData;


            // Build Android native UI
            mInflater = LayoutInflater.from(appActivity);
            dynNaviListItemUI = (View)mInflater.inflate(R.layout.prpl_facade_navi_list_item,
            									        null, false);
            ImageView listItem_image = (ImageView)dynNaviListItemUI.findViewById(R.id.naviList_item_photo);
            TextView listItem_upperText = (TextView)dynNaviListItemUI.findViewById(R.id.naviList_item_upperText);
            TextView listItem_lowerText = (TextView)dynNaviListItemUI.findViewById(R.id.naviList_item_lowerText);

            String pageTitle = null, actionCall = null;
            
            if (this.listEntryNewPageTitle != null) {
               pageTitle = UIModelData.fillStrWithAttr(currentUIData, this.listEntryNewPageTitle).trim();
            }
            if (this.listEntryActionCall != null){
               actionCall = UIModelData.fillStrWithAttr(currentUIData, this.listEntryActionCall).trim();
            }
            
            
            // Whether a thumbnail should be displayed for this list-entry
            if (this.listEntryImage != null)
            {
                String picAddr = UIModelData.fillStrWithAttr(currentUIData, this.listEntryImage).trim();
                // XML did specify an image url address
                if (!picAddr.equals(this.listEntryImage)) 
                {
                    try
                    {
                           URL aURL = new URL(picAddr); // picAddr is the URL of the image
                           URLConnection con = aURL.openConnection();
                           con.connect();
                           InputStream is = con.getInputStream();
                           /* Buffered is always good for a performance plus. */
                           BufferedInputStream bis = new BufferedInputStream(is);
                           
                           /* Decode url-data to a bitmap. */
                           //BitmapFactory.Options options = new BitmapFactory.Options();                          
                           //options.outWidth = listItem_image.getWidth();                             
                           Bitmap bm = BitmapFactory.decodeStream(bis); //BitmapFactory.decodeStream(bis, null, options);
                           
                           /* Apply the Bitmap to the ImageView that will be returned. */
                           listItem_image.setScaleType(ImageView.ScaleType.FIT_XY);
                           listItem_image.setImageBitmap(bm);
                           bis.close(); is.close();
                    }
                    catch (IOException e)
                    {
                          Log.e("DEBUGTAG", "Remote Image Exception", e);
                    } 
                	
                    listItem_upperText.setText(listEntryText);
                    listItem_lowerText.setVisibility(View.GONE);
                }
                else 
                {
                	listItem_upperText.setText(listEntryText);
                	listItem_image.setVisibility(View.GONE);
                	listItem_lowerText.setVisibility(View.GONE);
                }
            }
            else
            {
            	listItem_upperText.setText(listEntryText);
            	listItem_image.setVisibility(View.GONE);
            	listItem_lowerText.setVisibility(View.GONE);
            }



            // Action Bundle
        	HashMap<String, Object> actionBundle = new HashMap<String, Object>();
        	actionBundle.put("pageTitle", pageTitle);
        	actionBundle.put("actionCall", actionCall);
        	actionBundle.put("platformData", platformData);
        	

            // Possible action results when clicking on this list item entry
            // Response currently handled by ListView's OnItemClickListener
            if (this.listEntryAction == listEntryActions.SHOW_NEWLISTPAGE)
            {                   
            	actionBundle.put("action", "showNewListPage");
            	
            	// dynNaviListItemUI.setClickable(true);
            	
            	// Setup call back to Application/Actvity code to handle certain types of
                // user-interaction with UI, such as the clicking of a selection
                //if (platformData instanceof FacadeAndroidData)
                //{
                //	FacadeAndroidData appData = (FacadeAndroidData)platformData;
                //	dynNaviListItemUI.setOnClickListener(appData.getAppClickResponse());
                //}
                //else
                //{
                //	dynNaviListItemUI.setClickable(false);
                //}
            	
            	// generateAndroidUI_showNewListPage(currentUIData, platformData);
            }
            else if (this.listEntryAction == listEntryActions.SHOW_CUSTOMPAGE)
            {
            	actionBundle.put("action", "showCustomPage");
            }
            else if (this.listEntryAction == listEntryActions.EXPAND_SUBLIST)
            {
            	actionBundle.put("action", "expandSublist");
            }
            else if (this.listEntryAction == listEntryActions.EXTERNAL_LINK)
            {
            	actionBundle.put("action", "externalLink");
            	
            	// Launch intent to invoke browser to open external link
            	// UI_htmlcode += "<a href=\""+this.listEntryActionCall+"\" target=\"_self\">"+listEntryText+"</a></li>";
            }
            else
            {
            	actionBundle.put("action", "none");	
            	
            	// NOT CLICKABLE, JUST DISPLAY-ONLY
            	// dynNaviListItemUI.setClickable(false);
            }
            
            dynNaviListItemUI.setTag(actionBundle);
            currentUIData.uiObject = dynNaviListItemUI;
        }
        

	} // end of DynNaviListEntryUITemplate



	/* Android specific */
	private class DynNaviListAdapter extends ArrayAdapter<View>
	{	
        private ArrayList<View> list_items;
        private LayoutInflater mInflater;

        public DynNaviListAdapter(Context context, int textViewResourceId, ArrayList<View> items) 
        {
                super(context, textViewResourceId, items);
                this.list_items = items;
                this.mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) 
        {
                View v = convertView;
                v = list_items.get(position);
                return v;
        }
	}
	
	/* Android specific */
	public static class DynNaviListActionResponder
	{
		private static final DynNaviListActionResponder responder = new DynNaviListActionResponder();

		private DynNaviListActionResponder()
		{ /* Singleton */ }

		public static DynNaviListActionResponder getInstance()
		{
			return responder;
		}

		public OnClickListener appClickResponse = null;		
		public final OnClickListener mClickEvent = new OnClickListener()
	    {
			public void onClick(View v)
			{
				String pageTitle = null, action = null, actionCall = null;
				HashMap<String, Object> actionBundle = (HashMap<String, Object>)v.getTag();
				// Object platformData = null;
				// Intent i = getIntent();

	        	if (actionBundle != null)
				{
					pageTitle    = (String)actionBundle.get("pageTitle");
					action       = (String)actionBundle.get("action");
					actionCall   = (String)actionBundle.get("actionCall");
					//platformData = (FacadeAndroidData)actionBundle.get("platformData");
				}


				if (action == null || action.equals("none"))
		           return;
				else if (action.equals("showNewListPage"))
				{
				   if (appListItemClickResponse != null)
			 	      appClickResponse.onClick(v);
				   return;
				}
				else if (action.equals("showCustomPage"))
			    {
				   Log.d("Facade.OnClickListener", "Show Custom Page");
				   return;
				}
				else if (action.equals("expandSublist"))
				   return;
				else if (action.equals("externalLink"))
				   return;
				else
				   return;
			}
	    };
		
		public OnItemClickListener appListItemClickResponse = null;
		public final OnItemClickListener mListItemClickEvent = new OnItemClickListener()
	    {
			public void onItemClick(AdapterView<?> adapter, View v, int pos, long id)
			{
				String pageTitle = null, action = null, actionCall = null;
				// Object platformData = null;
				
				/* Clicked on a separator row. */
				if (id == -1)
					return;

				Log.d("Facade.OnItemClickListener", "in onItemClick");
				
				HashMap<String, Object> actionBundle = (HashMap<String, Object>)v.getTag();
				// Intent i = getIntent();
				
				if (actionBundle != null)
				{
					pageTitle  = (String)actionBundle.get("pageTitle");
					action     = (String)actionBundle.get("action");
					actionCall = (String)actionBundle.get("actionCall");
					//platformData = (FacadeAndroidData)actionBundle.get("platformData");
				}
	        	
				if (action == null || action.equals("none"))
	        	   return;
				else if (action.equals("showNewListPage"))
				{
				   if (appListItemClickResponse != null)
					  appListItemClickResponse.onItemClick(adapter, v, pos, id);
				   return;
				}
				else if (action.equals("showCustomPage"))
				{
				   Log.d("Facade.OnItemClickListener", "Show Custom Page");
				   return;
				}
				else if (action.equals("expandSublist"))
				   return;
				else if (action.equals("externalLink"))
				   return;
				else
				   return;
			}
	    };
		
	}

	
	
}